package com.tgh.gles2.c7.sphereMap;

import com.tgh.gles2.BaseRenderer;
import com.tgh.gles2.R;
import com.tgh.utils.GLFrame;
import com.tgh.utils.GLFrustum;
import com.tgh.utils.GLGeometryTransform;
import com.tgh.utils.GLMatrixStack;
import com.tgh.utils.GLShaderManager;
import com.tgh.utils.GLTools;
import com.tgh.utils.GLTriangleBatch;

import android.content.Context;
import android.opengl.GLES20;
import android.os.SystemClock;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class SphereMapRenderer extends BaseRenderer {

    public SphereMapRenderer(Context context) {
        super(context);
        torusBatch = new GLTriangleBatch();
        if (!torusBatch.loadDataFromSD("torus_08_025_52_26")) {
            torusBatch=GLTools.makeTorus(0.8f, 0.25f, 52, 26);
            torusBatch.cacheDataToSD("torus_08_025_52_26");
        }
        viewFrame=new GLFrame();
        modelViewMatrix=new GLMatrixStack();
        projectionMatrix=new GLMatrixStack();
        transformPipleLine=new GLGeometryTransform();
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        initTexture();
        initProgram();
        viewFrame.moveForward(4.0f);
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        viewFrustum=new GLFrustum(35, (float)width/(float)height, 1, 100);
        projectionMatrix.loadMatrix(viewFrustum.getProjectionMatrix());
        transformPipleLine.setMatrixStack(modelViewMatrix, projectionMatrix);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
        modelViewMatrix.pushMatrix(viewFrame);
            modelViewMatrix.rotate(SystemClock.elapsedRealtime()/100, 0, 1, 0);
            
            GLES20.glUseProgram(sphereMapShader);
            GLES20.glUniformMatrix4fv(locMvMatrix, 1, false, modelViewMatrix.getMatrix().getArray(), 0);
            GLES20.glUniformMatrix4fv(locPMatrix, 1, false, projectionMatrix.getMatrix().getArray(), 0);
            GLES20.glUniform1i(locSphereMap, 0);
            
            torusBatch.draw();
        modelViewMatrix.popMatrix();
    }

    @Override
    public void onSurfaceDestroyed() {
        GLES20.glDeleteTextures(1, textures, 0);
    }
    
    private void initTexture() {
        textures = GLTools.genTextures(1);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        GLTools.loadDrawableToTexture2D(
                mContext,
                R.drawable.sphere_map, 
                GLES20.GL_LINEAR_MIPMAP_LINEAR, 
                GLES20.GL_LINEAR, 
                GLES20.GL_CLAMP_TO_EDGE , 
                true);
    }
    
    private void initProgram() {
        String vpSrc = GLShaderManager.readFileFromAssets(mContext, "SphereMapped.vp");
        String fpSrc = GLShaderManager.readFileFromAssets(mContext, "SphereMapped.fp");
        sphereMapShader = GLShaderManager.createProgram(vpSrc, fpSrc, 
                new int[]{GLShaderManager.GL_ATTRIBUTE_VERTEX,GLShaderManager.GL_ATTRIBUTE_NORMAL}, 
                new String[]{"vVertex","vNormal"}
        );
        locMvMatrix = GLES20.glGetUniformLocation(sphereMapShader, "mvMatrix");
        locPMatrix = GLES20.glGetUniformLocation(sphereMapShader, "pMatrix");
        locSphereMap = GLES20.glGetUniformLocation(sphereMapShader, "sphereMap");
    }
    private GLFrame viewFrame;
    private GLFrustum viewFrustum;
    private GLMatrixStack modelViewMatrix;
    private GLMatrixStack projectionMatrix;
    private GLGeometryTransform transformPipleLine;
    private int sphereMapShader;
    private int locSphereMap;
    private int locPMatrix;
    private int locMvMatrix;
    private int[] textures;
    private GLTriangleBatch torusBatch;
    
}
